home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
os2
/
ext2_200.zip
/
EXT2_SRC.ZIP
/
32BITS
/
EXT2-OS2
/
FSD32
/
FS32_MOU.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-21
|
15KB
|
381 lines
//
// $Header: D:/32bits/ext2-os2/fsd32/RCS/fs32_mount.c,v 1.1 1996/09/21 22:25:25 Willm Exp Willm $
//
// 32 bits Linux ext2 file system driver for OS/2 WARP - Allows OS/2 to
// access your Linux ext2fs partitions as normal drive letters.
// Copyright (C) 1995, 1996 Matthieu WILLM
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifdef __IBMC__
#pragma strings(readonly)
#endif
#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_NOPMAPI
#include <os2.h>
#include <string.h>
#include <os2/types.h>
#include <os2/StackToFlat.h>
#include <linux/fs.h>
#include <os2/os2proto.h>
#include <os2/fsd32.h>
#include <os2/fsh32.h>
#include <os2/DevHlp32.h>
#include <os2/log.h>
#include <os2/trace.h>
#include <os2/errors.h>
#include <os2/files.h>
#include <os2/volume.h>
#include <linux/fs_proto.h>
#include <linux/ext2_proto.h>
#include <linux/stat.h>
#include <os2/vfsapi.h>
#include <os2/ifsdbg.h>
#define ERROR_VOLUME_NOT_MOUNTED 0xEE00 // IFS specific
extern char Use_Extended_Interface;
extern struct file_system_type ext2_fs_type;
struct super_block * do_mount(
struct vpfsi32 *pvpfsi,
union vpfsd32 *pvpfsd,
unsigned short hVPB,
struct file_system_type *type
) {
struct super_block *tmp;
struct super_block *sb;
int rc;
sb = get_empty_super();
pvpfsd->u.sb = sb;
if ((sb) && (sb->s_magic_internal == SUPER_MAGIC)) {
sb->sector_size = pvpfsi->vpi_bsize;
sb->nb_sectors = pvpfsi->vpi_totsec;
sb->s_drive = pvpfsi->vpi_drive;
sb->s_unit = pvpfsi->vpi_unit;
sb->s_blocksize = BLOCK_SIZE;
sb->sectors_per_block = BLOCK_SIZE / sb->sector_size;
sb->s_dev = hVPB;
sb->s_status = VOL_STATUS_MOUNT_IN_PROGRESS;
if (!Read_Write)
sb->s_flags = MS_RDONLY;
/*
* Strategy 2 I/O support processing
*/
if (Use_Extended_Interface) {
struct DriverCaps32 *pDCS;
struct VolChars32 *pVCS;
if (pvpfsi->vpi_pDCS.seg) {
if ((rc = DevHlp32_VirtToLin(pvpfsi->vpi_pDCS, __StackToFlat(&pDCS))) == NO_ERROR) {
if (pvpfsi->vpi_pVCS.seg) {
if ((rc = DevHlp32_VirtToLin(pvpfsi->vpi_pVCS, __StackToFlat(&pVCS))) == NO_ERROR) {
if ((pDCS) && (pDCS->Strategy2.seg)) {
kernel_printf("\tStrategy 2 entry point found");
if (pVCS) {
kernel_printf("\tVolume descriptor : 0x%04X", pVCS->VolDescriptor); /* see equates below */
kernel_printf("\tAverage seek time : %d", pVCS->AvgSeekTime); /* milliseconds, if unknown, FFFFh */
kernel_printf("\tAverage latency time : %d", pVCS->AvgLatency); /* milliseconds, if unknown, FFFFh */
kernel_printf("\tBlocks on smallest track : %d", pVCS->TrackMinBlocks); /* blocks on smallest track */
kernel_printf("\tBlocks on largest track : %d", pVCS->TrackMaxBlocks); /* blocks on largest track */
kernel_printf("\tMax scatter-gather list : %d", pVCS->MaxSGList); /* Adapter scatter/gather list limit */
}
if ((pVCS) && (pVCS->VolDescriptor & VC_REMOVABLE_MEDIA)) {
kernel_printf("\tMedia is removable, not supported for strat 2 yet !");
} else {
kernel_printf("\tMedia is NOT removable, using strat 2 I/Os");
sb->s_strat2.seg = pDCS->Strategy2.seg;
sb->s_strat2.ofs = pDCS->Strategy2.ofs;
}
} else {
kernel_printf("\tNO strategy 2 entry point found, using standard FSH_DOVOLIO instead");
}
} else {
kernel_printf("\tError while thunking pvpfsi->vpi_pVCS - rc = %d", rc);
}
}
} else {
kernel_printf("\tError while thunking pvpfsi->vpi_pDCS - rc = %d", rc);
}
}
} else {
kernel_printf("\tUsing standard I/Os as requested on the IFS command line.");
}
if ((type) && (type->read_super)) {
tmp = type->read_super(sb, 0, 0);
if (tmp) {
sb->s_blocks_per_page = (unsigned char)(4096 / sb->s_blocksize);
sb->s_status = VOL_STATUS_MOUNTED;
/*
* nothing else to do ...
*/
} else {
put_super(sb);
sb = 0;
}
} else {
sb = 0;
}
} else {
sb = 0;
}
return sb;
}
/*
* Alters the mount flags of a mounted file system. Only the mount point
* is used as a reference - file system type and the device are ignored.
* FS-specific mount options can't be altered by remounting.
*/
int do_remount_sb(struct super_block *sb, int flags, char *data)
{
int retval;
#ifndef OS2
if (!(flags & MS_RDONLY ) && sb->s_dev && is_read_only(sb->s_dev))
return -EACCES;
/*flags |= MS_RDONLY;*/
/* If we are remounting RDONLY, make sure there are no rw files open */
if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
if (!fs_may_remount_ro(sb->s_dev))
return -EBUSY;
#endif
if (sb->s_op && sb->s_op->remount_fs) {
retval = sb->s_op->remount_fs(sb, __StackToFlat(&flags), data);
if (retval)
return retval;
}
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) |
(flags & MS_RMT_MASK);
return 0;
}
int do_unmount(struct super_block *sb) {
if (!fs_may_umount(sb->s_dev, sb->s_mounted)) {
kernel_printf("\tdo_unmount WARNING !! device busy");
return ERROR_DEVICE_IN_USE;
}
invalidate_files(sb, 1);
sync_buffers(sb->s_dev, 1);
iput(sb->s_mounted);
sync_inodes(sb->s_dev);
sync_buffers(sb->s_dev, 1);
if (!sb->s_is_swapper_device) {
invalidate_inodes(sb->s_dev);
sync_buffers(sb->s_dev, 1);
}
if ((sb->s_op) && (sb->s_op->put_super))
sb->s_op->put_super(sb);
sync_buffers(sb->s_dev, 1);
if (!sb->s_is_swapper_device) {
invalidate_buffers(sb->s_dev);
}
put_super(sb);
sync_buffers(0, 1);
sync_buffers(0, 1);
return NO_ERROR;
}
extern int check_ext2fs_magic(struct vpfsi32 *pvpfsi, unsigned short hVPB);
/*
* struct fs32_mount_parms {
* PTR16 pBoot;
* unsigned short hVPB;
* PTR16 pvpfsd;
* PTR16 pvpfsi;
* unsigned short flag;
* };
*/
int FS32ENTRY fs32_mount(struct fs32_mount_parms *parms) {
struct vpfsi32 *pvpfsi;
union vpfsd32 *pvpfsd;
char *pBoot;
int rc;
int i;
struct super_block *sb;
struct super_block *old_sb;
unsigned short oldhVPB;
parms = __StackToFlat(parms);
if ((rc = DevHlp32_VirtToLin(parms->pvpfsi, __StackToFlat(&pvpfsi))) == NO_ERROR) {
if ((rc = DevHlp32_VirtToLin(parms->pvpfsd, __StackToFlat(&pvpfsd))) == NO_ERROR) {
switch(parms->flag) {
case MOUNT_MOUNT :
kernel_printf("FS_MOUNT flg = MOUNT_MOUNT hVPB = 0x%04X", parms->hVPB);
if ((rc = DevHlp32_VirtToLin(parms->pBoot, __StackToFlat(&pBoot))) == NO_ERROR) {
/*
* We zero out pvpfsd for safety purposes !
*/
memset(pvpfsd, 0, sizeof(union vpfsd32));
if ((rc = check_ext2fs_magic(pvpfsi, parms->hVPB)) == NO_ERROR) {
/*
* The volume serial number is a CRC checksum of the boot sector
*/
pvpfsi->vpi_vid = updcrc((unsigned char *)pBoot, pvpfsi->vpi_bsize);
/*
* The volume label is dummy for the moment ("ext2fs_<drive>")
*/
sprintf(pvpfsi->vpi_text, "EXT2FS_%c", pvpfsi->vpi_unit + 'A');
/*
* Is there another instance of the drive ?
* - Yes : update internal volume table and return silently
* - No : continue the mount process
*/
if ((rc = fsh32_findduphvpb(parms->hVPB, __StackToFlat(&oldhVPB))) == NO_ERROR) {
kernel_printf(" \tFSH_FINDDUPHVPB(0x%0X) - Found dup hVPB 0x%0X", (int)parms->hVPB, (int)oldhVPB);
old_sb = getvolume(oldhVPB);
if ((old_sb) && (old_sb->s_magic_internal == SUPER_MAGIC)) {
old_sb->s_status = VOL_STATUS_MOUNTED;
rc = NO_ERROR;
} else {
kernel_printf("Cannot find old superblock !");
rc = ERROR_INVALID_PARAMETER;
}
} else {
kernel_printf(" \tFSH_FINDDUPHVPB - NO dup hVPB");
/*
* This is the first instance of the drive
*/
sb = do_mount(pvpfsi, pvpfsd, parms->hVPB, &ext2_fs_type);
if (sb) {
kernel_printf("Volume characteristics :");
kernel_printf("========================");
kernel_printf("\t volume id : 0x%08X", pvpfsi->vpi_vid);
kernel_printf("\t hDEV : 0x%08X", pvpfsi->vpi_hDEV);
kernel_printf("\t sector size : %u", pvpfsi->vpi_bsize);
kernel_printf("\t sector/track : %u", pvpfsi->vpi_trksec);
kernel_printf("\t heads : %u", pvpfsi->vpi_nhead);
kernel_printf("\t tot sectors : %lu", pvpfsi->vpi_totsec);
kernel_printf("\t drive (0=A) : %d", (int)(pvpfsi->vpi_drive));
kernel_printf("\t unit code : %d", (int)(pvpfsi->vpi_unit));
kernel_printf("\t volume label : %s", pvpfsi->vpi_text);
kernel_printf("\t hVPB : 0x%08X", parms->hVPB);
sb->s_status = VOL_STATUS_MOUNTED;
pvpfsd->u.sb = sb;
rc = NO_ERROR;
} else {
rc = ERROR_VOLUME_NOT_MOUNTED;
}
}
} else {
kernel_printf("\tbasic superblock validation failed for volume 0x%04X", (int)parms->hVPB);
rc = ERROR_VOLUME_NOT_MOUNTED;
}
} else {
kernel_printf("FS_MOUNT - couldn't thunk pBoot");
}
break;
case MOUNT_VOL_REMOVED :
kernel_printf("FS_MOUNT flg = MOUNT_VOL_REMOVED hVPB = 0x%04X", parms->hVPB);
if ((pvpfsd->u.sb) && (pvpfsd->u.sb->s_magic_internal == SUPER_MAGIC)) {
pvpfsd->u.sb->s_status = VOL_STATUS_REMOVED;
rc = NO_ERROR;
} else {
rc = ERROR_INVALID_PARAMETER;
}
break;
case MOUNT_RELEASE :
kernel_printf("FS_MOUNT flg = MOUNT_RELEASE hVPB = 0x%04X", parms->hVPB);
if ((pvpfsd->u.sb) && (pvpfsd->u.sb->s_magic_internal == SUPER_MAGIC)) {
kernel_printf("\tvalid superblock present in VPB");
switch(pvpfsd->u.sb->s_status) {
case VOL_STATUS_REMOVED:
kernel_printf("\tmedia is NOT present");
/*
* This is a "hard" unmount !!
*/
invalidate_files(pvpfsd->u.sb, 0);
hard_invalidate_inodes(pvpfsd->u.sb->s_dev);
if ((pvpfsd->u.sb->s_op) && (pvpfsd->u.sb->s_op->put_super))
pvpfsd->u.sb->s_op->put_super(pvpfsd->u.sb);
invalidate_buffers(pvpfsd->u.sb->s_dev);
put_super(pvpfsd->u.sb);
memset(pvpfsd, 0, sizeof(union vpfsd32));
rc = NO_ERROR;
break;
case VOL_STATUS_MOUNTED:
kernel_printf("\tmedia is present");
rc = do_unmount(pvpfsd->u.sb);
memset(pvpfsd, 0, sizeof(union vpfsd32));
break;
default:
kernel_printf("FS_MOUNT - unexpected volume status");
rc = ERROR_INVALID_PARAMETER;
break;
}
} else {
kernel_printf("\tNO superblock present in VPB (probably unmounting a dup VPB)");
rc = NO_ERROR;
}
break;
case MOUNT_ACCEPT :
kernel_printf("FS_MOUNT flg = MOUNT_ACCEPT hVPB = 0x%04X", parms->hVPB);
// rc = ERROR_NOT_SUPPORTED;
rc = NO_ERROR;
break;
default :
kernel_printf("FS_MOUNT() invalid flag %d", parms->flag);
rc = ERROR_INVALID_PARAMETER;
break;
}
}
}
return rc;
}